package com.data;

import static com.utils.ConstantVariables.L_MAX;
import static com.utils.ConstantVariables.M;
import static com.utils.ConstantVariables.g;

import java.util.StringTokenizer;

import com.utils.ConstantVariables;

/**
 * Node
 * 
 * @author bh349
 */
public class Node implements Comparable<Node> {
	private double x;
	private double y;
	private int[] groupNumbers;
	private boolean intersection;
	private TreeNode tn;

	// used in union-find
	private Node parent = null;

	public Node getParent() {
		if (parent == null) {
			parent = this;
		}
		return parent;
	}

	public void setParent(Node parent) {
		this.parent = parent;
		if (!this.equals(parent)) {
			System.out.println(this + " points to " + parent);
		}
	}

	public Node(double x, double y) {
		this.x = x;
		this.y = y;
		this.groupNumbers = calculateGroupNumbers();
		tn = new TreeNode(x, y);
	}

	public Node(String value) {
		StringTokenizer st = new StringTokenizer(value);
		double[] vals = new double[2];
		for (int i = 0; i < 2 && st.hasMoreElements(); i++) {
			vals[i] = Double.parseDouble(st.nextToken());
		}
		this.x = vals[0];
		this.y = vals[1];
		tn = new TreeNode(x, y);
	}

	public boolean isIntersection() {
		return intersection;
	}

	public double getX() {
		return x;
	}

	public double getY() {
		return y;
	}

	public static boolean isWithinDistance(Node a, Node b) {
		return Math.pow((a.getX() - b.getX()), 2)
				+ Math.pow((a.getY() - b.getY()), 2) <= Math.pow(
				L_MAX[ConstantVariables.testNumber], 2);
	}

	public static boolean isXFar(Node a, Node b) {
		if (Math.abs(a.getX() - b.getX()) > L_MAX[ConstantVariables.testNumber]) {
			return true;
		}
		return false;
	}

	private int[] calculateGroupNumbers() {
		int[] result = new int[2];
		intersection = true;
		result[0] = (int) Math.floor(x / g[ConstantVariables.testNumber]);

		double leftBound = (double) result[0] * g[ConstantVariables.testNumber];
		double rightBound = (double) (result[0] + 1)
				* g[ConstantVariables.testNumber];
		if (x >= leftBound
				&& x <= leftBound + L_MAX[ConstantVariables.testNumber] / 2
				&& result[0] != 0) {
			result[1] = result[0] - 1;
		} else if (x >= rightBound - L_MAX[ConstantVariables.testNumber] / 2
				&& x <= rightBound
				&& result[0] != M[ConstantVariables.testNumber] - 1) {
			result[1] = result[0] + 1;
		} else {
			result[1] = -1;
			intersection = false;
		}
		return result;
	}

	public int[] getGroupNumbers() {
		return groupNumbers;
	}

	@Override
	public String toString() {
		StringBuilder sb = new StringBuilder();
		sb.append(x);
		sb.append(" ");
		sb.append(y);
		return sb.toString();
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		long temp;
		temp = Double.doubleToLongBits(x);
		result = prime * result + (int) (temp ^ (temp >>> 32));
		temp = Double.doubleToLongBits(y);
		result = prime * result + (int) (temp ^ (temp >>> 32));
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj) {
			return true;
		}
		if (obj == null) {
			return false;
		}
		if (getClass() != obj.getClass()) {
			return false;
		}
		Node other = (Node) obj;
		if (Double.doubleToLongBits(x) != Double.doubleToLongBits(other.x)) {
			return false;
		}
		if (Double.doubleToLongBits(y) != Double.doubleToLongBits(other.y)) {
			return false;
		}
		return true;
	}

	public TreeNode getNodeForRedBlackTree() {
		return tn;
	}

	/**
	 * return -1 if this node is to the left of target node. 0 if same and 1 if
	 * to the right.
	 */
	public int compareTo(Node o) {
		// this shouldn't happen
		if (x == o.x && y == o.y) {
			return 0;
		}
		// x is dominating
		if (x < o.x) {
			return -1;
		} else if (x == o.x && y < o.y) {
			return -1;
		} else {
			return 1;
		}

	}

	public static void main(String[] args) {
		Node n = new Node(0.3782568, 0.34554);
		int[] outs = n.getGroupNumbers();
		System.out.println(ConstantVariables.g[1]);
		System.out.println(ConstantVariables.M[1]);
		System.out.println(outs[0]);
		System.out.println(outs[1]);
	}
}
